package br.edu.infnet.avaliacao.dao.hibernate;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Query;

public class DAO<T> extends GenericDAO {

	private static Logger logger = Logger.getLogger(DAO.class);
	@SuppressWarnings("rawtypes")
	private final Class classe;

	/**
	 * Contrutor que cria um novo dao mais especifico, porem no modelo generico,
	 * pegando uma sessao e a classe em questao para a criacao do dao.
	 * 
	 * @param session
	 * @param classe
	 */
	@SuppressWarnings("rawtypes")
	public DAO(Class classe) {
		this.classe = classe;
	}

	/**
	 * Persiste o objeto passado como parametro.
	 * 
	 * @param u
	 */
	public void incluir(T t) {
		logger.info("incluindo  " + t);
		try {
			session = getSession();
			session.beginTransaction();
			session.save(t);
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			logger.fatal(e);
		} finally {
			session.close();
		}
	}

	/**
	 * Remove o objeto persistido do banco de dados.
	 * 
	 * @param u
	 */
	public void deletar(T t) {
		logger.info("Deletando  " + t);

		try {
			if (t != null) {
				session = getSession();
				session.beginTransaction();
				session.delete(t);
				session.getTransaction().commit();
			}
		} catch (Exception e) {
			session.getTransaction().rollback();
			logger.fatal(e);
		} finally {
			session.close();
		}
	}

	/**
	 * Copia o estado do objeto pegando o objeto persistido com identificador
	 * igual ao que foi passado como parametro.
	 * 
	 * @param u
	 */
	public void atualizar(T t) {
		logger.info("Atualizando  " + t);

		try {
			session = getSession();
			session.beginTransaction();
			session.merge(t);
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			logger.fatal(e);
		} finally {
			session.close();

		}
	}

	/**
	 * Lista todos os objetos existentes na entidade em questao.
	 * 
	 * @return List<T>
	 */
	@SuppressWarnings("unchecked")
	public List<T> listar() {
		logger.info("listando ");
		return this.session.createCriteria(this.classe).list();
	}

	/**
	 * Retorna a instancia peristida da classe de entidade e o identificador
	 * passados como parametro, assume que a instancia exista.
	 * 
	 * @param id
	 * @return T
	 */
	@SuppressWarnings("unchecked")
	public T consultar(Integer id) {
		logger.info("procurando  " + id);
		return (T) session.get(this.classe, id);
	}

	public Long getTotalRegistro() {
		logger.info("Totalizando  ");

		Long total = new Long(0);
		try {
			session = getSession();
			session.beginTransaction();
			Query q = session.createQuery("select count(p) as total from "
					+ this.classe.getName() + " p");
			total = (Long) q.list().get(0);
			session.getTransaction().commit();
		} catch (Exception e) {
			session.getTransaction().rollback();
			logger.fatal(e);
		} finally {
			session.close();
		}
		return total;
	}
}